package fmfi.chatbox;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.facebook.android.Facebook;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.widget.Toast;

public class Messenger
{
	public String key = "";
	public String fbUserID = "";
	public String fbToken = "";
	public HttpClient httpClient = new DefaultHttpClient();
	public Activity activity = null;
	
	public Messenger(Activity activity, String key, String fbUserID, String fbToken)
	{
		this.activity = activity;
		this.key = key;
		this.fbUserID = fbUserID;
		this.fbToken = fbToken;
		
		// bez tohto to proste nejde
		StrictMode.ThreadPolicy policy = new StrictMode.
		ThreadPolicy.Builder().permitAll().build();
		StrictMode.setThreadPolicy(policy); 
	}
	
	private JSONObject getJSONFromResponse(HttpResponse response) throws IllegalStateException, IOException, JSONException
	{
		HttpEntity entity = response.getEntity(); // ziskam data ktore dosli ako input stream
		InputStream content = entity.getContent();
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(content)); // zaobalim stream, aby som mohol citat po riadkoch 
		StringBuilder builder = new StringBuilder(); // tu budem vkladat nacitavane riadky
		String line; // toto je riadok ktory nacitam
		
		while ((line = reader.readLine()) != null) // citam dokym je co citat
			builder.append(line); // vkladam riadky do string buildera
		
		return new JSONObject(builder.toString()); // z nacitaneho stringu vytvorim JSON object
	}
	
	@SuppressWarnings("deprecation")
	public String fillUsername(List<Message> messages)
	{
		// ziskam id-cka userov, ktori poslali spravy (ziskam ich tak, aby user ktory poslal viac sprav bol v iba raz)
		Map<String, String> mapUsers = new TreeMap<String, String>(); // <userID, userName>
		for (Message msg : messages)
		{
			if (msg.fbUserID != "0")
				mapUsers.put(msg.fbUserID, "");
		}
		
		Facebook fb = new Facebook("406708959404720");
		String prefix = "SELECT uid,name FROM user WHERE uid IN (";
		String infix = "";
		for (Map.Entry<String, String> uid : mapUsers.entrySet()) // generujem podmieku WHERE
		{
			if (infix != "")
				infix += ", ";
			infix += uid.getKey();
		}
		String postfix = ")";
		String query = prefix + infix + postfix;
		Bundle params = new Bundle();
		params.putString("method", "fql.query");
		params.putString("query", query);
		String response = "";
		
		try
		{
			response = fb.request(params); 
		}
		catch (Exception e)
		{
			Toast.makeText(activity, "Facebook request error", Toast.LENGTH_SHORT).show();
			return "";
		}
		
		try
		{
			JSONArray jsonArray = new JSONArray(response);
			
			for (int i = 0; i < jsonArray.length(); ++i)
			{
				try
				{
					JSONObject jsonObj = jsonArray.getJSONObject(i);
					mapUsers.put(jsonObj.getString("uid"), jsonObj.getString("name"));
				}
				catch (JSONException e){} // ak exception, len pokracuj dalsim cyklom
			}
		}
		catch (JSONException e)
		{
			Toast.makeText(activity, "Root JSON array error", Toast.LENGTH_SHORT).show();
			return "";
		}
		
		for (Message m : messages)
		{
			String userName = mapUsers.get(m.fbUserID);
			m.fbUserName = userName != null ? userName : "";
		}
		
		return "";
	}

	@SuppressLint("SimpleDateFormat")
	public Message[] getMessages(Date timestamp)
	{
		String timeFrom = (timestamp != null) ? (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")).format(timestamp) : "-1";
		System.out.println(timeFrom);
		String strURI = "http://lu-pa.sk/vma2012/api/?key=" + key + "&lastPullTimestamp=" + timeFrom;
		try
		{
			HttpGet request = new HttpGet(new URI(strURI)); // get request
			HttpResponse response = httpClient.execute(request); // odosle, vrati sa responce
			StatusLine statusLine = response.getStatusLine();
			if (statusLine.getStatusCode() == 200) // kontrolujem ci doslo HTTP OK
			{
				JSONObject jsonRoot = getJSONFromResponse(response);
				if (jsonRoot.getString("status") == "error") // ak dosiel JSON error - da end
				{
					Toast.makeText(activity, jsonRoot.getString("error"), Toast.LENGTH_SHORT).show();
					return null;
				}
				JSONArray jsonMessages = jsonRoot.getJSONArray("messages"); // ziskam array sprav
				List<Message> msgList = new ArrayList<Message>(); // tu sa budu hadzat ziskane spravy
				for (int m = 0; m < jsonMessages.length(); ++m) // prelezem vsekty spravy v JSON
				{
					JSONObject jsonMsg = jsonMessages.getJSONObject(m); // ziskam JSON spravu na indexe
					Message msg = new Message(); // vytvorim si svoju vlastnu spravu
					try // ziskavam z jednotlivych JSON atributy spravy
					{
						msg.fbUserID = jsonMsg.getString("facebookUserID");
						//msg.fbUserName = getUsername2(msg.fbUserID);
						msg.message = jsonMsg.getString("messageText");
						msg.datetime = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")).parse( jsonMsg.getString("timestamp") );
						msg.latitutde = Double.parseDouble( jsonMsg.getString("lat") );
						msg.longitude = Double.parseDouble( jsonMsg.getString("lon") );
					}
					catch (JSONException e){} // ak sa nieco nepodari, ulozim si to co uz mam a pokracujem dalsou spravou
					msgList.add(msg);
				}
				fillUsername(msgList);
				Message[] msgArray = new Message[msgList.size()]; // pole sprav ktore vratim, alokujem pre vsetky spravy
				return msgList.toArray(msgArray); // list to array and return
			}
			else // ak nevysiel HTTP request
			{
				Toast.makeText(activity, statusLine.getReasonPhrase(), Toast.LENGTH_SHORT).show();
				return null;
			}
		}
		catch (Exception e)
		{
			Toast.makeText(activity, e.getMessage(), Toast.LENGTH_SHORT).show();
			return null;
		}
	}
	
	@SuppressLint("SimpleDateFormat")
	public boolean sendMessage(String text)
	{
		String strURI = "http://lu-pa.sk/vma2012/api/";
		try
		{
			HttpPost request = new HttpPost(new URI(strURI)); // post request
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(new BasicNameValuePair("key", key));
			String now = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")).format(new Date());
			nameValuePairs.add(new BasicNameValuePair("lastPullTimestamp", now));
			nameValuePairs.add(new BasicNameValuePair("facebookUserID", fbUserID));
			nameValuePairs.add(new BasicNameValuePair("facebookToken", fbToken));
			nameValuePairs.add(new BasicNameValuePair("messageText", text));
			//nameValuePairs.add(new BasicNameValuePair("lat", ""));
			//nameValuePairs.add(new BasicNameValuePair("lon", ""));
			request.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse response = httpClient.execute(request); // odosle, vrati sa responce
			StatusLine statusLine = response.getStatusLine();
			if (statusLine.getStatusCode() == 200) // kontrolujem ci doslo HTTP OK
			{
				JSONObject jsonRoot = getJSONFromResponse(response);
				if (jsonRoot.getString("status") == "error")
				{
					System.out.println(jsonRoot.getString("error"));
					Toast.makeText(activity, jsonRoot.getString("error"), Toast.LENGTH_SHORT).show();
					return false;
				}
				else
					return true;
			}
			else // ak nevysiel HTTP request
			{
				System.out.println(statusLine.getReasonPhrase());
				Toast.makeText(activity, statusLine.getReasonPhrase(), Toast.LENGTH_SHORT).show();
				return false;
			}
		}
		catch (Exception e)
		{
			System.out.println(e.getMessage());
			Toast.makeText(activity, e.getMessage(), Toast.LENGTH_SHORT).show();
			return false;
		}
	}
	
}
